﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Transactions;
using SZORM.Core;
using SZORM.Extensions;
using SZORM.Infrastructure;
using SZORM.Infrastructure.Interception;
using SZORM.Utility;

namespace SZORM.Core
{
    /// <summary>
    /// 数据库会话管理核心类，负责数据库连接池管理、事务处理、SQL命令执行及资源释放
    /// 实现了IAsyncDisposable接口以支持异步资源释放，提供同步和异步两种操作模式
    /// </summary>
    class InternalAdoSession : IAsyncDisposable
    {
        /// <summary>
        /// 数据库连接对象
        /// </summary>
        DbConnection _dbConnection;
        /// <summary>
        /// 数据库事务对象
        /// </summary>
        DbTransaction _dbTransaction;
        /// <summary>
        /// 是否处于事务中
        /// </summary>
        bool _isInTransaction;
        /// <summary>
        /// 命令执行超时时间(秒)
        /// </summary>
        int _commandTimeout = 30;

        /// <summary>
        /// 数据库命令拦截器列表
        /// </summary>
        List<DbCommandInterceptor> _dbCommandInterceptors;

        /// <summary>
        /// 是否已释放资源
        /// </summary>
        bool _disposed = false;

        /// <summary>
        /// 数据库连接字符串
        /// </summary>
        string _connectionString;

        public InternalAdoSession()
        {
        }
        /// <summary>
        /// 初始化InternalAdoSession实例
        /// </summary>
        /// <param name="factory">数据库提供程序工厂</param>
        /// <param name="connectionString">数据库连接字符串</param>
        public InternalAdoSession(IDatabaseProvider factory, string connectionString)
        {
            _connectionString = connectionString;
            _dbConnection = DbConnectionPool.Rent(factory, connectionString);
        }

        public static async Task<InternalAdoSession> CreateAsync(IDatabaseProvider factory, string connectionString)
        {
            var instance = new InternalAdoSession();
            await instance.InitializeAsync(factory, connectionString);
            return instance;
        }

        private async Task InitializeAsync(IDatabaseProvider factory, string connectionString)
        {
            _connectionString = connectionString;
            _dbConnection = await DbConnectionPool.RentAsync(factory, connectionString);
        }


        public IDbConnection DbConnection { get { return _dbConnection; } }
        /// <summary>
        /// 如果未开启事务，则返回 null
        /// </summary>
        public IDbTransaction DbTransaction { get { return _dbTransaction; } }
        /// <summary>
        /// 获取当前会话是否处于事务中
        /// </summary>
        public bool IsInTransaction { get { return _isInTransaction; } }
        /// <summary>
        /// 获取或设置命令执行超时时间(秒)
        /// </summary>
        public int CommandTimeout { get { return _commandTimeout; } set { _commandTimeout = value; } }
        /// <summary>
        /// 获取数据库命令拦截器列表，若为空则初始化
        /// </summary>
        public List<DbCommandInterceptor> DbCommandInterceptors
        {
            get
            {
                _dbCommandInterceptors ??= [];

                return _dbCommandInterceptors;
            }
        }

        /// <summary>
        /// 异步开始数据库事务
        /// </summary>
        /// <param name="il">事务隔离级别，为null时使用默认隔离级别</param>
        public async Task BeginTransactionAsync(System.Data.IsolationLevel? il = null)
        {
            if (Transaction.Current == null)
            {
                if (il == null)
                {
                    _dbTransaction ??= await _dbConnection.BeginTransactionAsync();
                }
                else
                {
                    _dbTransaction ??= await _dbConnection.BeginTransactionAsync(il.Value);
                }
                _isInTransaction = true;
            }
        }

        /// <summary>
        /// 同步开始数据库事务
        /// </summary>
        /// <param name="il">事务隔离级别，为null时使用默认隔离级别</param>
        public void BeginTransaction(System.Data.IsolationLevel? il = null)
        {
            //Activate();

            if (Transaction.Current == null)
            {
                if (il == null)
                {
                    _dbTransaction ??= _dbConnection.BeginTransaction();
                }
                else
                {
                    _dbTransaction ??= _dbConnection.BeginTransaction(il.Value);
                }
                _isInTransaction = true;
            }
        }
        /// <summary>
        /// 提交当前事务
        /// </summary>
        /// <exception cref="SZORMException">当未开启事务时抛出</exception>
        public void CommitTransaction()
        {
            if (!_isInTransaction)
            {
                throw new SZORMException("Current session does not open a transaction.");
            }
            _dbTransaction.Commit();
            ReleaseTransaction();
        }
        public async Task CommitTransactionAsync()
        {
            if (!_isInTransaction)
            {
                throw new SZORMException("Current session does not open a transaction.");
            }
            await _dbTransaction.CommitAsync();
            await ReleaseTransactionAsync();
        }
        public void RollbackTransaction()
        {
            if (!_isInTransaction)
            {
                throw new SZORMException("Current session does not open a transaction.");
            }
            _dbTransaction.Rollback();
            ReleaseTransaction();
            //Complete();
        }
        public async Task RollbackTransactionAsync()
        {
            if (!_isInTransaction)
            {
                throw new SZORMException("Current session does not open a transaction.");
            }
            await _dbTransaction.RollbackAsync();
            await ReleaseTransactionAsync();
        }
        /// <summary>
        /// 同步执行SQL命令并返回数据读取器
        /// </summary>
        /// <param name="cmdText">要执行的SQL语句</param>
        /// <param name="parameters">SQL命令参数数组</param>
        /// <param name="cmdType">命令类型</param>
        /// <returns>包含查询结果的IDataReader</returns>
        public IDataReader ExecuteReader(string cmdText, DbParam[] parameters, CommandType cmdType)
        {
            return ExecuteReader(cmdText, parameters, cmdType, CommandBehavior.Default);
        }
        public IDataReader ExecuteReader(string cmdText, DbParam[] parameters, CommandType cmdType, CommandBehavior behavior)
        {
            CheckDisposed();

            DbCommand cmd = PrepareCommand(cmdText, parameters, cmdType, out List<OutputParameter> outputParameters);

            DbCommandInterceptionContext<IDataReader> dbCommandInterceptionContext = new();
            DbCommandInterceptor[] globalInterceptors = DbInterception.GetInterceptors();

            //Activate();
            OnReaderExecuting(cmd, dbCommandInterceptionContext, globalInterceptors);

            IDataReader reader;
            try
            {
                reader = new InternalDataReader(this, cmd.ExecuteReader(behavior), cmd, outputParameters);
            }
            catch (Exception ex)
            {
                dbCommandInterceptionContext.Exception = ex;
                OnReaderExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);

                throw WrapException(ex);
            }

            dbCommandInterceptionContext.Result = reader;
            OnReaderExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);

            return reader;
        }
        /// <summary>
        /// 异步执行SQL命令并返回数据读取器
        /// </summary>
        /// <param name="cmdText">要执行的SQL语句</param>
        /// <param name="parameters">SQL命令参数数组</param>
        /// <param name="cmdType">命令类型</param>
        /// <returns>包含查询结果的IDataReader</returns>
        public async Task<IDataReader> ExecuteReaderAsync(string cmdText, DbParam[] parameters, CommandType cmdType)
        {
            return await ExecuteReaderAsync(cmdText, parameters, cmdType, CommandBehavior.Default);
        }
        public async Task<IDataReader> ExecuteReaderAsync(string cmdText, DbParam[] parameters, CommandType cmdType, CommandBehavior behavior)
        {
            CheckDisposed();

            DbCommand cmd = PrepareCommand(cmdText, parameters, cmdType, out List<OutputParameter> outputParameters);

            DbCommandInterceptionContext<IDataReader> dbCommandInterceptionContext = new();
            DbCommandInterceptor[] globalInterceptors = DbInterception.GetInterceptors();

            //Activate();
            OnReaderExecuting(cmd, dbCommandInterceptionContext, globalInterceptors);

            IDataReader reader;
            try
            {
                reader = new InternalDataReader(this, await cmd.ExecuteReaderAsync(behavior), cmd, outputParameters);
            }
            catch (Exception ex)
            {
                dbCommandInterceptionContext.Exception = ex;
                OnReaderExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);

                throw WrapException(ex);
            }

            dbCommandInterceptionContext.Result = reader;
            OnReaderExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);

            return reader;
        }

        /// <summary>
        /// 同步执行SQL命令并返回受影响的行数
        /// </summary>
        /// <param name="cmdText">要执行的SQL语句</param>
        /// <param name="parameters">SQL命令参数数组</param>
        /// <param name="cmdType">命令类型</param>
        /// <returns>受影响的行数</returns>
        public int ExecuteNonQuery(string cmdText, DbParam[] parameters, CommandType cmdType)
        {
            CheckDisposed();

            DbCommand cmd = null;
            try
            {
                cmd = PrepareCommand(cmdText, parameters, cmdType, out List<OutputParameter> outputParameters);

                DbCommandInterceptionContext<int> dbCommandInterceptionContext = new();
                DbCommandInterceptor[] globalInterceptors = DbInterception.GetInterceptors();

                //Activate();
                OnNonQueryExecuting(cmd, dbCommandInterceptionContext, globalInterceptors);

                int rowsAffected;
                try
                {
                    rowsAffected = cmd.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    dbCommandInterceptionContext.Exception = ex;
                    OnNonQueryExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);

                    throw WrapException(ex);
                }

                dbCommandInterceptionContext.Result = rowsAffected;
                OnNonQueryExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);
                OutputParameter.CallMapValue(outputParameters);

                return rowsAffected;
            }
            finally
            {
                //Complete();
                cmd?.Dispose();
            }
        }
        /// <summary>
        /// 异步执行SQL命令并返回受影响的行数
        /// </summary>
        /// <param name="cmdText">要执行的SQL语句</param>
        /// <param name="parameters">SQL命令参数数组</param>
        /// <param name="cmdType">命令类型</param>
        /// <returns>受影响的行数</returns>
        public async Task<int> ExecuteNonQueryAsync(string cmdText, DbParam[] parameters, CommandType cmdType)
        {
            CheckDisposed();

            DbCommand cmd = null;
            try
            {
                cmd = PrepareCommand(cmdText, parameters, cmdType, out List<OutputParameter> outputParameters);

                DbCommandInterceptionContext<int> dbCommandInterceptionContext = new();
                DbCommandInterceptor[] globalInterceptors = DbInterception.GetInterceptors();

                //Activate();
                OnNonQueryExecuting(cmd, dbCommandInterceptionContext, globalInterceptors);

                int rowsAffected;
                try
                {
                    rowsAffected = await cmd.ExecuteNonQueryAsync();
                }
                catch (Exception ex)
                {
                    dbCommandInterceptionContext.Exception = ex;
                    OnNonQueryExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);

                    throw WrapException(ex);
                }

                dbCommandInterceptionContext.Result = rowsAffected;
                OnNonQueryExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);
                OutputParameter.CallMapValue(outputParameters);

                return rowsAffected;
            }
            finally
            {
                cmd?.Dispose();
            }
        }
        /// <summary>
        /// 同步执行SQL命令并返回结果集中的第一行第一列
        /// </summary>
        /// <param name="cmdText">要执行的SQL语句</param>
        /// <param name="parameters">SQL命令参数数组</param>
        /// <param name="cmdType">命令类型</param>
        /// <returns>结果集中的第一行第一列，若结果集为空则返回null</returns>
        public object ExecuteScalar(string cmdText, DbParam[] parameters, CommandType cmdType)
        {
            CheckDisposed();

            DbCommand cmd = null;
            try
            {
                cmd = PrepareCommand(cmdText, parameters, cmdType, out List<OutputParameter> outputParameters);

                DbCommandInterceptionContext<object> dbCommandInterceptionContext = new();
                DbCommandInterceptor[] globalInterceptors = DbInterception.GetInterceptors();

                //Activate();
                OnScalarExecuting(cmd, dbCommandInterceptionContext, globalInterceptors);

                object ret;
                try
                {
                    ret = cmd.ExecuteScalar();
                }
                catch (Exception ex)
                {
                    dbCommandInterceptionContext.Exception = ex;
                    OnScalarExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);

                    throw WrapException(ex);
                }

                dbCommandInterceptionContext.Result = ret;
                OnScalarExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);
                OutputParameter.CallMapValue(outputParameters);

                return ret;
            }
            finally
            {
                //Complete();
                cmd?.Dispose();
            }
        }
        /// <summary>
        /// 异步执行SQL命令并返回结果集中的第一行第一列
        /// </summary>
        /// <param name="cmdText">要执行的SQL语句</param>
        /// <param name="parameters">SQL命令参数数组</param>
        /// <param name="cmdType">命令类型</param>
        /// <returns>结果集中的第一行第一列，若结果集为空则返回null</returns>
        public async Task<object> ExecuteScalarAsync(string cmdText, DbParam[] parameters, CommandType cmdType)
        {
            CheckDisposed();

            DbCommand cmd = null;
            try
            {
                cmd = PrepareCommand(cmdText, parameters, cmdType, out List<OutputParameter> outputParameters);

                DbCommandInterceptionContext<object> dbCommandInterceptionContext = new();
                DbCommandInterceptor[] globalInterceptors = DbInterception.GetInterceptors();

                //Activate();
                OnScalarExecuting(cmd, dbCommandInterceptionContext, globalInterceptors);

                object ret;
                try
                {
                    ret = await cmd.ExecuteScalarAsync();
                }
                catch (Exception ex)
                {
                    dbCommandInterceptionContext.Exception = ex;
                    OnScalarExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);

                    throw WrapException(ex);
                }

                dbCommandInterceptionContext.Result = ret;
                OnScalarExecuted(cmd, dbCommandInterceptionContext, globalInterceptors);
                OutputParameter.CallMapValue(outputParameters);

                return ret;
            }
            finally
            {
                cmd?.Dispose();
            }
        }

        /// <summary>
        /// 异步释放当前实例使用的非托管资源
        /// </summary>
        /// <returns>表示异步释放操作的Task</returns>
        public async Task DisposeAsync()
        {
            if (_disposed)
                return;

            if (_dbTransaction != null)
            {
                if (_isInTransaction)
                {
                    //_dbTransaction.Rollback();
                    if (Marshal.GetExceptionPointers() == IntPtr.Zero)
                    {
                        await _dbTransaction.CommitAsync();
                    }
                    else
                    {
                        try
                        {
                            await _dbTransaction.RollbackAsync();
                        }
                        catch
                        {
                        }
                    }
                }

                ReleaseTransaction();
            }

            if (_dbConnection != null)
            {
                DbConnectionPool.Return(_dbConnection, _connectionString);
            }

            _disposed = true;
        }

        public void Dispose()
        {
            if (_disposed)
                return;

            if (_dbTransaction != null)
            {
                if (_isInTransaction)
                {
                    if (Marshal.GetExceptionPointers() == IntPtr.Zero)
                    {
                        _dbTransaction.Commit();
                    }
                    else
                    {
                        try
                        {
                            _dbTransaction.Rollback();
                        }
                        catch
                        {
                        }
                    }
                }

                ReleaseTransaction();
            }

            if (_dbConnection != null)
            {
                DbConnectionPool.Return(_dbConnection, _connectionString);
            }

            _disposed = true;
        }

        #region 预编译参数

        /// <summary>
        /// 准备数据库命令对象，设置连接、事务、参数和超时时间
        /// </summary>
        /// <param name="cmdText">SQL命令文本</param>
        /// <param name="parameters">命令参数数组</param>
        /// <param name="cmdType">命令类型</param>
        /// <param name="outputParameters">输出参数列表</param>
        /// <returns>准备好的DbCommand对象</returns>
        DbCommand PrepareCommand(string cmdText, DbParam[] parameters, CommandType cmdType, out List<OutputParameter> outputParameters)
        {
            outputParameters = null;

            DbCommand cmd = _dbConnection.CreateCommand();

            cmd.CommandText = cmdText;
            cmd.CommandType = cmdType;
            cmd.CommandTimeout = _commandTimeout;
            if (IsInTransaction)
                cmd.Transaction = _dbTransaction;

            if (parameters != null)
            {
                for (int i = 0; i < parameters.Length; i++)
                {
                    DbParam param = parameters[i];
                    if (param == null)
                        continue;

                    if (param.ExplicitParameter != null)/* 如果存在创建好了的 IDbDataParameter，则直接用它。同时也忽视了 DbParam 的其他属性 */
                    {
                        cmd.Parameters.Add(param.ExplicitParameter);
                        continue;
                    }

                    IDbDataParameter parameter = cmd.CreateParameter();
                    parameter.ParameterName = param.Name;

                    Type parameterType;
                    if (param.Value == null || param.Value == DBNull.Value)
                    {
                        parameter.Value = DBNull.Value;
                        parameterType = param.Type;
                    }
                    else
                    {
                        parameterType = param.Value.GetType();
                        if (parameterType.IsEnum)
                        {
                            parameterType = Enum.GetUnderlyingType(parameterType);
                            parameter.Value = Convert.ChangeType(param.Value, parameterType);
                        }
                        else
                        {
                            parameter.Value = param.Value;
                        }
                    }

                    if (param.Precision != null)
                        parameter.Precision = param.Precision.Value;

                    if (param.Scale != null)
                        parameter.Scale = param.Scale.Value;

                    if (param.Size != null)
                        parameter.Size = param.Size.Value;

                    if (param.DbType != null)
                        parameter.DbType = param.DbType.Value;
                    else
                    {
                        DbType? dbType = MappingTypeSystem.GetDbType(parameterType);
                        if (dbType != null)
                            parameter.DbType = dbType.Value;
                    }

                    const int defaultSizeOfStringOutputParameter = 4000;/* 当一个 string 类型输出参数未显示指定 Size 时使用的默认大小。如果有需要更大或者该值不足以满足需求，需显示指定 DbParam.Size 值 */

                    OutputParameter outputParameter = null;
                    if (param.Direction == ParamDirection.Input)
                    {
                        parameter.Direction = ParameterDirection.Input;
                    }
                    else if (param.Direction == ParamDirection.Output)
                    {
                        parameter.Direction = ParameterDirection.Output;
                        param.Value = null;
                        if (param.Size == null && param.Type == UtilConstants.TypeOfString)
                        {
                            parameter.Size = defaultSizeOfStringOutputParameter;
                        }
                        outputParameter = new OutputParameter(param, parameter);
                    }
                    else if (param.Direction == ParamDirection.InputOutput)
                    {
                        parameter.Direction = ParameterDirection.InputOutput;
                        if (param.Size == null && param.Type == UtilConstants.TypeOfString)
                        {
                            parameter.Size = defaultSizeOfStringOutputParameter;
                        }
                        outputParameter = new OutputParameter(param, parameter);
                    }
                    else
                        throw new NotSupportedException(string.Format("ParamDirection '{0}' is not supported.", param.Direction));

                    cmd.Parameters.Add(parameter);

                    if (outputParameter != null)
                    {
                        outputParameters ??= [];
                        outputParameters.Add(outputParameter);
                    }
                }
            }

            return cmd;
        }
        #endregion


        #region DbInterception
        /// <summary>
        /// 触发命令执行前的拦截器事件
        /// </summary>
        /// <param name="cmd">即将执行的数据库命令</param>
        /// <param name="dbCommandInterceptionContext">命令拦截上下文</param>
        /// <param name="globalInterceptors">全局命令拦截器</param>
        void OnReaderExecuting(DbCommand cmd, DbCommandInterceptionContext<IDataReader> dbCommandInterceptionContext, DbCommandInterceptor[] globalInterceptors)
        {
            ExecuteDbCommandInterceptors((dbCommandInterceptor) =>
            {
                dbCommandInterceptor.ReaderExecuting(cmd, dbCommandInterceptionContext);
            }, globalInterceptors);
        }
        /// <summary>
        /// 触发命令执行后的拦截器事件（带数据读取器）
        /// </summary>
        /// <param name="cmd">已执行的数据库命令</param>
        /// <param name="dbCommandInterceptionContext">命令拦截上下文</param>
        /// <param name="globalInterceptors">全局命令拦截器</param>
        void OnReaderExecuted(DbCommand cmd, DbCommandInterceptionContext<IDataReader> dbCommandInterceptionContext, DbCommandInterceptor[] globalInterceptors)
        {
            ExecuteDbCommandInterceptors((dbCommandInterceptor) =>
            {
                dbCommandInterceptor.ReaderExecuted(cmd, dbCommandInterceptionContext);
            }, globalInterceptors);
        }
        void OnNonQueryExecuting(DbCommand cmd, DbCommandInterceptionContext<int> dbCommandInterceptionContext, DbCommandInterceptor[] globalInterceptors)
        {
            ExecuteDbCommandInterceptors((dbCommandInterceptor) =>
            {
                dbCommandInterceptor.NonQueryExecuting(cmd, dbCommandInterceptionContext);
            }, globalInterceptors);
        }
        void OnNonQueryExecuted(DbCommand cmd, DbCommandInterceptionContext<int> dbCommandInterceptionContext, DbCommandInterceptor[] globalInterceptors)
        {
            ExecuteDbCommandInterceptors((dbCommandInterceptor) =>
            {
                dbCommandInterceptor.NonQueryExecuted(cmd, dbCommandInterceptionContext);
            }, globalInterceptors);
        }
        void OnScalarExecuting(DbCommand cmd, DbCommandInterceptionContext<object> dbCommandInterceptionContext, DbCommandInterceptor[] globalInterceptors)
        {
            ExecuteDbCommandInterceptors((dbCommandInterceptor) =>
            {
                dbCommandInterceptor.ScalarExecuting(cmd, dbCommandInterceptionContext);
            }, globalInterceptors);
        }
        void OnScalarExecuted(DbCommand cmd, DbCommandInterceptionContext<object> dbCommandInterceptionContext, DbCommandInterceptor[] globalInterceptors)
        {
            ExecuteDbCommandInterceptors((dbCommandInterceptor) =>
            {
                dbCommandInterceptor.ScalarExecuted(cmd, dbCommandInterceptionContext);
            }, globalInterceptors);
        }

        void ExecuteDbCommandInterceptors(Action<DbCommandInterceptor> act, DbCommandInterceptor[] globalInterceptors)
        {
            for (int i = 0; i < globalInterceptors.Length; i++)
            {
                act(globalInterceptors[i]);
            }

            if (_dbCommandInterceptors != null)
            {
                for (int i = 0; i < _dbCommandInterceptors.Count; i++)
                {
                    act(_dbCommandInterceptors[i]);
                }
            }
        }
        #endregion
        /// <summary>
        /// 异步释放事务并将连接归还连接池
        /// </summary>
        async Task ReleaseTransactionAsync()
        {
            await _dbTransaction.DisposeAsync();
            _dbTransaction = null;
            _isInTransaction = false;
        }

        /// <summary>
        /// 同步释放事务并将连接归还连接池
        /// </summary>
        void ReleaseTransaction()
        {
            _dbTransaction.Dispose();
            _dbTransaction = null;
            _isInTransaction = false;
        }


        /// <summary>
        /// 检查当前实例是否已释放，若已释放则抛出ObjectDisposedException
        /// </summary>
        /// <exception cref="ObjectDisposedException">当实例已释放时抛出</exception>
        void CheckDisposed()
        {
            ObjectDisposedException.ThrowIf(_disposed, this);
        }


        public static string AppendDbCommandInfo(string cmdText, DbParam[] parameters)
        {
            StringBuilder sb = new();
            if (parameters != null)
            {
                foreach (DbParam param in parameters)
                {
                    if (param == null)
                        continue;

                    string typeName = null;
                    Type parameterType;
                    object value;
                    if (param.Value == null || param.Value == DBNull.Value)
                    {
                        parameterType = param.Type;
                        value = "NULL";
                    }
                    else
                    {
                        value = param.Value;
                        parameterType = param.Value.GetType();

                        if (parameterType == typeof(string) || parameterType == typeof(DateTime))
                            value = "'" + value + "'";
                    }

                    if (parameterType != null)
                        typeName = GetTypeName(parameterType);

                    sb.AppendFormat("{0} {1} = {2};", typeName, param.Name, value);
                    sb.AppendLine();
                }
            }

            sb.AppendLine(cmdText);

            return sb.ToString();
        }
        static string GetTypeName(Type type)
        {
            if (ReflectionExtension.IsNullable(type, out Type underlyingType))
            {
                return string.Format("Nullable<{0}>", GetTypeName(underlyingType));
            }

            return type.Name;
        }

        static SZORMException WrapException(Exception ex)
        {
            return new SZORMException("An exception occurred while executing DbCommand. For details please see the inner exception.", ex);
        }

        /// <summary>
        /// 异步释放资源
        /// </summary>
        /// <returns>表示异步释放操作的ValueTask</returns>
        ValueTask IAsyncDisposable.DisposeAsync()
        {
            return DisposeAsyncCore();
        }

        /// <summary>
        /// 核心异步释放方法
        /// </summary>
        /// <returns>表示异步释放操作的ValueTask</returns>
        private async ValueTask DisposeAsyncCore()
        {
            if (_disposed)
                return;

            if (_dbTransaction != null)
            {
                if (_isInTransaction)
                {
                    try
                    {
                        if (Marshal.GetExceptionPointers() == IntPtr.Zero)
                        {
                            await _dbTransaction.CommitAsync().ConfigureAwait(false);
                        }
                        else
                        {
                            await _dbTransaction.RollbackAsync().ConfigureAwait(false);
                        }
                    }
                    catch { }
                }
                await ReleaseTransactionAsync().ConfigureAwait(false);
            }

            if (_dbConnection != null)
            {
                DbConnectionPool.Return(_dbConnection, _connectionString);
            }

            _disposed = true;
        }
    }
}
